package com.snailwu.redis.semaphore;

import cn.hutool.core.thread.ThreadUtil;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.StringRedisTemplate;

import javax.annotation.Resource;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@SpringBootApplication
public class RedisSemaphoreApplication implements ApplicationRunner {

    public static void main(String[] args) {
        SpringApplication.run(RedisSemaphoreApplication.class, args);
    }

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Bean(name = "demoSemaphore")
    public RedisSemaphore demoSemaphore() {
        return new RedisSemaphore("semaphore:demo", 1, 5000, stringRedisTemplate);
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        RedisSemaphore semaphore = demoSemaphore();

        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5,
                1, TimeUnit.MINUTES, new LinkedBlockingQueue<>());
        for (int i = 0; i < 3; i++) {
            executor.submit(() -> {
                while (true) {
                    if (!semaphore.tryAcquire()) {
                        ThreadUtil.sleep(100);
                    }
                    try {
                        // 执行业务逻辑。。。
                    } finally {
                        // 这里释放信号量可以是本机器进行释放，也可以是其他机器进行释放（如果部署多实例的话）
                        semaphore.release();
                    }
                }
            });
        }
    }

}
